/*
 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2015 NXP Semiconductors
 * The original Work has been changed by NXP Semiconductors.
 *
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "_OverrideLog.h"
#include "SecureElement.h"
#include "JavaClassConstants.h"
#include "PowerSwitch.h"
#include "NfcTag.h"
#include "RoutingManager.h"
#include <ScopedPrimitiveArray.h>
#include "phNxpConfig.h"

#define ALOGV ALOGD
extern bool hold_the_transceive;
extern int dual_mode_current_state;
extern bool ceTransactionPending;
namespace android
{

extern void startRfDiscovery (bool isStart);
extern bool isDiscoveryStarted();
extern bool isp2pActivated();
extern void com_android_nfc_NfcManager_disableDiscovery (JNIEnv* e, jobject o);
extern void com_android_nfc_NfcManager_enableDiscovery (JNIEnv* e, jobject o, jint mode);
#if (NXP_EXTNS == TRUE)
extern int gMaxEERecoveryTimeout;
#endif
static SyncEvent            sNfaVSCResponseEvent;
//static bool sRfEnabled;           /*commented to eliminate warning defined but not used*/

static void nfaVSCCallback(uint8_t event, uint16_t param_len, uint8_t *p_param);

inline static void nfaVSCCallback(uint8_t event, uint16_t param_len, uint8_t *p_param)    /*defined as inline to eliminate warning defined but not used*/
{
    (void)event;
    (void)param_len;
    (void)p_param;
    SyncEventGuard guard (sNfaVSCResponseEvent);
    sNfaVSCResponseEvent.notifyOne ();
}

// These must match the EE_ERROR_ types in NfcService.java
static const int EE_ERROR_IO = -1;
static const int EE_ERROR_INIT = -3;
static const int EE_ERROR_LISTEN_MODE = -4;
static const int EE_ERROR_EXT_FIELD = -5;

/*******************************************************************************
**
** Function:        nativeNfcSecureElement_doOpenSecureElementConnection
**
** Description:     Connect to the secure element.
**                  e: JVM environment.
**                  o: Java object.
**
** Returns:         Handle of secure element.  values < 0 represent failure.
**
*******************************************************************************/
#if (NXP_EXTNS == TRUE)
static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv*, jobject,jint seId)
#else
static jint nativeNfcSecureElement_doOpenSecureElementConnection (JNIEnv*, jobject)
#endif
{
    ALOGV("%s: enter", __func__);
    bool stat = false;
    jint secElemHandle = EE_ERROR_INIT;
    long ret_val = -1;
    NFCSTATUS status = NFCSTATUS_FAILED;
    p61_access_state_t p61_current_state = P61_STATE_INVALID;
    se_apdu_gate_info gateInfo = NO_APDU_GATE;
    SecureElement &se = SecureElement::getInstance();
#if (NXP_EXTNS == TRUE)
    if(nfcFL.nfcNxpEse) {
        if(!nfcFL.eseFL._ESE_WIRED_MODE_PRIO && se.isBusy()) {
            goto TheEnd;
        }
        se.mIsExclusiveWiredMode = false; // to ctlr exclusive wired mode
        if(seId == 0xF4)
        {
            if(se.mIsWiredModeOpen)
            {
                goto TheEnd;
            }
            if(nfcFL.eseFL._ESE_UICC_EXCLUSIVE_WIRED_MODE) {
                se.mIsExclusiveWiredMode = true;
            }
            stat = se.checkForWiredModeAccess();
            if(stat == false)
            {
                ALOGV("Denying SE open due to SE listen mode active");
                secElemHandle = EE_ERROR_LISTEN_MODE;
                goto TheEnd;
            }

            ALOGV("%s: Activating UICC Wired Mode=0x%X", __func__, seId);
            stat = se.activate(seId);
            ALOGV("%s: Check UICC activation status stat=%X", __func__, stat);
            if (stat)
            {
                //establish a pipe to UICC
                ALOGV("%s: Creatting a pipe to UICC!", __func__);
                stat = se.connectEE();
                if (stat)
                {
                    secElemHandle = se.mActiveEeHandle;
                }
                else
                {
                    se.deactivate (0);
                }
            }
            if ((!stat) && (! PowerSwitch::getInstance ().setModeOff (PowerSwitch::SE_CONNECTED)))
            {
                PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER);
            }
            se.mIsWiredModeOpen = true;
            if(nfcFL.eseFL._ESE_UICC_EXCLUSIVE_WIRED_MODE) {
                if (isDiscoveryStarted())
                {
                    // Stop RF Discovery if we were polling
                    startRfDiscovery (false);
                    status = NFA_DisableListening();
                    if(status == NFCSTATUS_OK)
                    {
                        startRfDiscovery (true);
                    }
                }
                else
                {
                    status = NFA_DisableListening();
                }
                se.mlistenDisabled = true;
            }
            goto TheEnd;
            if(nfcFL.eseFL._ESE_WIRED_MODE_PRIO) {
                if(se.mIsWiredModeOpen&&(se.mActiveEeHandle == (se.EE_HANDLE_0xF4 || SecureElement::EE_HANDLE_0xF8)))
                {
                    stat = SecureElement::getInstance().disconnectEE (se.mActiveEeHandle);
                    se.mActiveEeHandle = NFA_HANDLE_INVALID;
                    se.mIsWiredModeOpen = false;
                }
            }

            if(nfcFL.chipType != pn547C2) {
                if(nfcFL.nfccFL._NFCEE_REMOVED_NTF_RECOVERY && (RoutingManager::getInstance().is_ee_recovery_ongoing()))
                {
                    SyncEventGuard guard (se.mEEdatapacketEvent);
                    if(se.mEEdatapacketEvent.wait(android::gMaxEERecoveryTimeout) == false)
                    {
                        goto TheEnd;
                    }
                }
                if(nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME ==
                        nfcFL.eseFL._ESE_UICC_EXCLUSIVE_WIRED_MODE) {

                    se.mIsExclusiveWiredMode = true;
                }
                stat = se.checkForWiredModeAccess();
                if(stat == false)
                {
                    ALOGV("Denying SE open due to SE listen mode active");
                    secElemHandle = EE_ERROR_LISTEN_MODE;
                    goto TheEnd;
                }
            }
            else
            {
                if (se.isActivatedInListenMode()) {
                    ALOGV("Denying SE open due to SE listen mode active");
                    secElemHandle = EE_ERROR_LISTEN_MODE;
                    goto TheEnd;
                }

                if (se.isRfFieldOn()) {
                    ALOGV("Denying SE open due to SE in active RF field");
                    secElemHandle = EE_ERROR_EXT_FIELD;
                    goto TheEnd;
                }
            }

            ret_val = NFC_GetP61Status ((void *)&p61_current_state);
            if (ret_val < 0)
            {
                ALOGV("NFC_GetP61Status failed");
                goto TheEnd;
            }
            ALOGV("P61 Status is: %x", p61_current_state);

            if(nfcFL.eseFL._ESE_JCOP_DWNLD_PROTECTION &&
                    (p61_current_state & P61_STATE_JCP_DWNLD))
                ALOGV("Denying SE open due to JCOP OS Download is in progress");
            secElemHandle = EE_ERROR_IO;
            goto TheEnd;
        }
    }


    if (((nfcFL.eseFL._NXP_ESE_VER == JCOP_VER_3_1)) &&(!(p61_current_state & P61_STATE_SPI) && !(p61_current_state & P61_STATE_SPI_PRIO))||(nfcFL.eseFL._NXP_ESE_VER != JCOP_VER_3_1))
    {
        if(p61_current_state & (P61_STATE_SPI)||(p61_current_state & (P61_STATE_SPI_PRIO)))
        {
            dual_mode_current_state |= SPI_ON;
        }
        if(p61_current_state & (P61_STATE_SPI_PRIO))
        {
            hold_the_transceive = true;
        }

        secElemHandle = NFC_ReqWiredAccess ((void *)&status);
        if (secElemHandle < 0)
        {
            ALOGV("Denying SE open due to NFC_ReqWiredAccess failed");
            goto TheEnd;
        }
        else
        {
            if (status != NFCSTATUS_SUCCESS)
            {
                ALOGV("Denying SE open due to SE is being used by SPI");
                secElemHandle = EE_ERROR_IO;
                goto TheEnd;
            }
            else
            {
                if(nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME == nfcFL.eseFL._ESE_UICC_EXCLUSIVE_WIRED_MODE) {
                    if (isDiscoveryStarted())
                    {
                        // Stop RF Discovery if we were polling
                        startRfDiscovery (false);
                        status = NFA_DisableListening();
                        if(status == NFCSTATUS_OK)
                        {
                            startRfDiscovery (true);
                        }
                    }
                    else
                    {
                        status = NFA_DisableListening();
                    }
                    se.mlistenDisabled = true;
                }
            }
        }
    }
    else
    {
        ALOGV("Denying SE open because SPI is already open");
        goto TheEnd;

    }
#endif
/* Tell the controller to power up to get ready for sec elem operations */
PowerSwitch::getInstance ().setLevel (PowerSwitch::FULL_POWER);
PowerSwitch::getInstance ().setModeOn (PowerSwitch::SE_CONNECTED);
/* If controller is not routing AND there is no pipe connected,
       then turn on the sec elem */
#if(NXP_EXTNS == TRUE)
if(nfcFL.nfcNxpEse) {
    if(nfcFL.eseFL._ESE_FORCE_ENABLE && (!(p61_current_state & (P61_STATE_SPI | P61_STATE_SPI_PRIO))) && (!(dual_mode_current_state & CL_ACTIVE)))
        stat = se.SecEle_Modeset(0x01); //Workaround
    usleep(150000); /*provide enough delay if NFCC enter in recovery*/
}
#endif
stat = se.activate(SecureElement::ESE_ID); // It is to get the current activated handle.

if (stat)
{
    //establish a pipe to sec elem
    stat = se.connectEE();
    if (stat)
    {
        secElemHandle = se.mActiveEeHandle;
    }
    else
    {
        se.deactivate (0);
    }
}
#if(NXP_EXTNS == TRUE)
if(nfcFL.nfcNxpEse && stat)
{
    status = NFA_STATUS_OK;
    if(nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) {
        if(!(se.isActivatedInListenMode() || isp2pActivated() || NfcTag::getInstance ().isActivated ()))
        {
            se.enablePassiveListen(0x00);
        }
        se.meseUiccConcurrentAccess = true;
    }

    if(nfcFL.eseFL._WIRED_MODE_STANDBY &&
            (se.mNfccPowerMode == 1))
    {
        status = se.setNfccPwrConfig(se.POWER_ALWAYS_ON|se.COMM_LINK_ACTIVE);
        if(status != NFA_STATUS_OK)
        {
            ALOGV("%s: power link command failed", __func__);
        }
        else
        {
            se.SecEle_Modeset(0x01);
        }
    }
#endif

    if((status == NFA_STATUS_OK) && (se.mIsIntfRstEnabled))
    {
        gateInfo = se.getApduGateInfo();
        ALOGV("%s: GateInfo %d", __func__, gateInfo);
        if(gateInfo == ETSI_12_APDU_GATE)
        {
            se.NfccStandByOperation(STANDBY_TIMER_STOP);
            status = se.SecElem_sendEvt_Abort();
            if(status != NFA_STATUS_OK)
            {
                ALOGV("%s: EVT_ABORT failed", __func__);
                se.sendEvent(SecureElement::EVT_END_OF_APDU_TRANSFER);
            }
        }
    }

    if(status != NFA_STATUS_OK)
    {
        if(nfcFL.eseFL._WIRED_MODE_STANDBY && (se.mNfccPowerMode == 1) &&
        !(p61_current_state & (P61_STATE_SPI | P61_STATE_SPI_PRIO))) {
            se.setNfccPwrConfig(se.NFCC_DECIDES);
        }
        se.disconnectEE (secElemHandle);
        secElemHandle = EE_ERROR_INIT;

        ret_val = NFC_RelWiredAccess((void*)&status);
        if(ret_val < 0)
            ALOGV("Denying SE release due to NFC_RelWiredAccess failure");
        else if(status != NFCSTATUS_SUCCESS)
            ALOGV("Denying SE close, since SE is not released by PN54xx driver");
    }
    else
    {
        se.mIsWiredModeOpen = true;
    }
}
//if code fails to connect to the secure element, and nothing is active, then
//tell the controller to power down
if ((!stat) && (! PowerSwitch::getInstance ().setModeOff (PowerSwitch::SE_CONNECTED)))
{
    PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER);
}

TheEnd:
ALOGV("%s: exit; return handle=0x%X", __func__, secElemHandle);
return secElemHandle;
}


/*******************************************************************************
**
** Function:        nativeNfcSecureElement_doDisconnectSecureElementConnection
**
** Description:     Disconnect from the secure element.
**                  e: JVM environment.
**                  o: Java object.
**                  handle: Handle of secure element.
**
** Returns:         True if ok.
**
*******************************************************************************/
static jboolean nativeNfcSecureElement_doDisconnectSecureElementConnection (JNIEnv*, jobject, jint handle)
{
    ALOGV("%s: enter; handle=0x%04x", __func__, handle);
    bool stat = false;
#if(NXP_EXTNS == TRUE)
    long ret_val = -1;
    NFCSTATUS status = NFCSTATUS_FAILED;

    SecureElement &se = SecureElement::getInstance();
    se.NfccStandByOperation(STANDBY_TIMER_STOP);
#endif

#if(NXP_EXTNS == TRUE)
    if(nfcFL.nfcNxpEse) {
        if(handle == (SecureElement::EE_HANDLE_0xF8||se.EE_HANDLE_0xF4))
        {
            stat = SecureElement::getInstance().disconnectEE (handle);
            if(nfcFL.nfcNxpEse) {
                se.mIsWiredModeOpen = false;
                if(nfcFL.eseFL._ESE_EXCLUSIVE_WIRED_MODE) {
                    se.mIsExclusiveWiredMode = false;
                    if(se.mlistenDisabled)
                    {
                        if (isDiscoveryStarted())
                        {
                            // Stop RF Discovery if we were polling
                            startRfDiscovery (false);
                            status = NFA_EnableListening();
                            startRfDiscovery (true);
                        }
                        else
                        {
                            status = NFA_EnableListening();
                        }
                        se.mlistenDisabled = false;
                    }
                }
            }
            goto TheEnd;
        }

        if(nfcFL.nfcNxpEse) {
            //Send the EVT_END_OF_APDU_TRANSFER event at the end of wired mode session.
            se.NfccStandByOperation(STANDBY_MODE_ON);
        }
    }
#endif

    stat = SecureElement::getInstance().disconnectEE (handle);

    /* if nothing is active after this, then tell the controller to power down */
    if (! PowerSwitch::getInstance ().setModeOff (PowerSwitch::SE_CONNECTED))
        PowerSwitch::getInstance ().setLevel (PowerSwitch::LOW_POWER);
#if(NXP_EXTNS == TRUE)
    if(nfcFL.nfcNxpEse) {
        ret_val = NFC_RelWiredAccess ((void *)&status);
        if (ret_val < 0)
        {
            ALOGV("Denying SE Release due to NFC_RelWiredAccess failed");
            goto TheEnd;
        }
        else
        {
            if (status != NFCSTATUS_SUCCESS)
            {
                ALOGV("Denying SE close due to SE is not being released by Pn54x driver");
                stat = false;
            }
            if(nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION) {
                se.enablePassiveListen(0x01);
                SecureElement::getInstance().mPassiveListenTimer.kill();
                se.meseUiccConcurrentAccess = false;
            }
            se.mIsWiredModeOpen = false;
            if((nfcFL.eseFL._ESE_DUAL_MODE_PRIO_SCHEME ==
                    nfcFL.eseFL._ESE_UICC_EXCLUSIVE_WIRED_MODE) && se.mlistenDisabled) {
                if (isDiscoveryStarted())
                {
                    // Stop RF Discovery if we were polling
                    startRfDiscovery (false);
                    status = NFA_EnableListening();
                    startRfDiscovery (true);
                }
                else
                {
                    status = NFA_EnableListening();
                }
                se.mlistenDisabled = false;
            }
        }
    }
#endif
TheEnd:
#if(NXP_EXTNS == TRUE)
if(nfcFL.nfcNxpEse) {
    ALOGV("%s: exit stat = %d", __func__, stat);
}
else {
    ALOGV("%s: exit", __func__);
}
#else
    ALOGV("%s: exit", __func__);
#endif

    return stat ? JNI_TRUE : JNI_FALSE;
}
#if(NXP_EXTNS == TRUE)
static int checkP61Status(void)
{
    if(!nfcFL.nfcNxpEse) {
        ALOGV("%s : nfcNxpEse not available. Returning", __func__);
        return -1;
    }
    jint ret_val = -1;
    p61_access_state_t p61_current_state = P61_STATE_INVALID;
    ret_val = NFC_GetP61Status ((void *)&p61_current_state);
    if (ret_val < 0)
    {
        ALOGV("NFC_GetP61Status failed");
        return -1;
    }
    if(p61_current_state & (P61_STATE_SPI)||(p61_current_state & (P61_STATE_SPI_PRIO)))
    {
        ALOGV("No gpio change");
        ret_val = 0;
    }
    else
    {
        ret_val = -1;
    }
    return ret_val;
}
#endif
/*******************************************************************************
**
** Function:        nativeNfcSecureElement_doResetSecureElement
**
** Description:     Reset the secure element.
**                  e: JVM environment.
**                  o: Java object.
**                  handle: Handle of secure element.
**
** Returns:         True if ok.
**
*******************************************************************************/
static jboolean nativeNfcSecureElement_doResetSecureElement (JNIEnv*, jobject, jint handle)
{
    bool stat = false;
    if(nfcFL.nfcNxpEse) {
        tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
        SecureElement &se = SecureElement::getInstance();

        ALOGV("%s: enter; handle=0x%04x", __func__, handle);
        if(!se.mIsWiredModeOpen)
        {
            ALOGV("wired mode is not open");
            return stat;
        }
        if(nfcFL.eseFL._ESE_DWP_SPI_SYNC_ENABLE && nfcFL.eseFL._WIRED_MODE_STANDBY && !checkP61Status()) {
            ALOGV("Reset is not allowed while SPI ON");
            return stat;
        }
        if(nfcFL.eseFL._WIRED_MODE_STANDBY && (se.mNfccPowerMode == 1))
        {
            nfaStat = se.setNfccPwrConfig(se.NFCC_DECIDES);
            ALOGV("%s Power Mode is Legacy", __func__);
        }
        {
            stat = se.SecEle_Modeset(0x00);
            if (handle == SecureElement::EE_HANDLE_0xF3)
            {
                if(checkP61Status())
                    se.NfccStandByOperation(STANDBY_GPIO_LOW);
            }
            usleep(100 * 1000);
            if (handle == SecureElement::EE_HANDLE_0xF3)
            {
                if(checkP61Status() && (se.mIsWiredModeOpen == true))
                    se.NfccStandByOperation(STANDBY_GPIO_HIGH);
            }

            if(nfcFL.eseFL._WIRED_MODE_STANDBY && (se.mNfccPowerMode == 1))
                stat = se.setNfccPwrConfig(se.POWER_ALWAYS_ON |se.COMM_LINK_ACTIVE);
            ALOGV("%s Power Mode is Legacy", __func__);
        }
        usleep(2000 * 1000);
        stat = se.SecEle_Modeset(0x01);
    }
ALOGV("%s: exit", __func__);
return stat ? JNI_TRUE : JNI_FALSE;
}

/*******************************************************************************
 **
** Function:        nativeNfcSecureElement_doeSEChipResetSecureElement
**
** Description:     Reset the secure element.
**                  e: JVM environment.
**                  o: Java object.
**                  handle: Handle of secure element.
**
** Returns:         True if ok.
**
*******************************************************************************/
static jboolean nativeNfcSecureElement_doeSEChipResetSecureElement (JNIEnv*, jobject)
{
    bool stat = false;
    NFCSTATUS status = NFCSTATUS_FAILED;
    unsigned long num = 0x01;
#if (NXP_EXTNS == TRUE)
    SecureElement &se = SecureElement::getInstance();
    if(nfcFL.nfcNxpEse) {
        if (GetNxpNumValue("NXP_ESE_POWER_DH_CONTROL", &num, sizeof(num)))
        {
            ALOGV("Power schemes enabled in config file is %ld", num);
        }
        if(num == 0x02)
        {
            status = se.eSE_Chip_Reset();
            if(status == NFCSTATUS_SUCCESS)
            {
                stat = true;
            }
        }
    }
#endif
    return stat ? JNI_TRUE : JNI_FALSE;
}


/*******************************************************************************
**
** Function:        nativeNfcSecureElement_doGetAtr
**
** Description:     GetAtr from the connected eSE.
**                  e: JVM environment.
**                  o: Java object.
**                  handle: Handle of secure element.
**
** Returns:         Buffer of received data.
**
*******************************************************************************/
static jbyteArray nativeNfcSecureElement_doGetAtr (JNIEnv* e, jobject, jint handle)
{
    bool stat = false;
    const int32_t recvBufferMaxSize = 1024;
    uint8_t recvBuffer [recvBufferMaxSize];
    int32_t recvBufferActualSize = 0;
    if(nfcFL.nfcNxpEse) {
        ALOGV("%s: enter; handle=0x%04x", __func__, handle);

        stat = SecureElement::getInstance().getAtr(handle, recvBuffer, &recvBufferActualSize);

        //copy results back to java
    }
    jbyteArray result = e->NewByteArray(recvBufferActualSize);
    if (result != NULL) {
        e->SetByteArrayRegion(result, 0, recvBufferActualSize, (jbyte *) recvBuffer);
    }

    ALOGV("%s: exit: recv len=%ld", __func__, recvBufferActualSize);

    return result;
}

/*******************************************************************************
**
** Function:        nativeNfcSecureElement_doTransceive
**
** Description:     Send data to the secure element; retrieve response.
**                  e: JVM environment.
**                  o: Java object.
**                  handle: Secure element's handle.
**                  data: Data to send.
**
** Returns:         Buffer of received data.
**
*******************************************************************************/
static jbyteArray nativeNfcSecureElement_doTransceive (JNIEnv* e, jobject, jint handle, jbyteArray data)
{
    const int32_t recvBufferMaxSize = 0x8800;//1024; 34k
    uint8_t recvBuffer [recvBufferMaxSize];
    int32_t recvBufferActualSize = 0;
    eTransceiveStatus tranStatus = TRANSCEIVE_STATUS_FAILED;

    ScopedByteArrayRW bytes(e, data);
#if(NXP_EXTNS == TRUE)
    ALOGV("%s: enter; handle=0x%X; buf len=%zu", __func__, handle, bytes.size());
    tranStatus = SecureElement::getInstance().transceive(reinterpret_cast<uint8_t*>(&bytes[0]), bytes.size(), recvBuffer, recvBufferMaxSize, recvBufferActualSize, WIRED_MODE_TRANSCEIVE_TIMEOUT);
    if(tranStatus == TRANSCEIVE_STATUS_MAX_WTX_REACHED)
    {
        ALOGE ("%s: Wired Mode Max WTX count reached", __FUNCTION__);
        jbyteArray result = e->NewByteArray(0);
        nativeNfcSecureElement_doResetSecureElement(e,NULL,handle);
        return result;
    }

    //copy results back to java
    jbyteArray result = e->NewByteArray(recvBufferActualSize);
    if (result != NULL)
    {
        e->SetByteArrayRegion(result, 0, recvBufferActualSize, (jbyte *) recvBuffer);
    }
    if (nfcFL.nfcNxpEse && nfcFL.eseFL._NFCC_ESE_UICC_CONCURRENT_ACCESS_PROTECTION &&
            (SecureElement::getInstance().mIsWiredModeBlocked == true))
    {
        ALOGV("APDU Transceive CE wait");
        SecureElement::getInstance().startThread(0x01);
    }
    ALOGV("%s: exit: recv len=%ld", __func__, recvBufferActualSize);
    return result;
#else
    jbyteArray result = e->NewByteArray(0);
    return result;
#endif
}

/*****************************************************************************
**
** Description:     JNI functions
**
*****************************************************************************/
static JNINativeMethod gMethods[] =
{
#if(NXP_EXTNS == TRUE)
   {"doNativeOpenSecureElementConnection", "(I)I", (void *) nativeNfcSecureElement_doOpenSecureElementConnection},
#else
    {"doNativeOpenSecureElementConnection", "()I", (void *) nativeNfcSecureElement_doOpenSecureElementConnection},
#endif
   {"doNativeDisconnectSecureElementConnection", "(I)Z", (void *) nativeNfcSecureElement_doDisconnectSecureElementConnection},
   {"doNativeResetSecureElement", "(I)Z", (void *) nativeNfcSecureElement_doResetSecureElement},
   {"doNativeeSEChipResetSecureElement", "()Z", (void *) nativeNfcSecureElement_doeSEChipResetSecureElement},
   {"doTransceive", "(I[B)[B", (void *) nativeNfcSecureElement_doTransceive},
   {"doNativeGetAtr", "(I)[B", (void *) nativeNfcSecureElement_doGetAtr},
};


/*******************************************************************************
**
** Function:        register_com_android_nfc_NativeNfcSecureElement
**
** Description:     Regisgter JNI functions with Java Virtual Machine.
**                  e: Environment of JVM.
**
** Returns:         Status of registration.
**
*******************************************************************************/
int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e)
{
    return jniRegisterNativeMethods(e, gNativeNfcSecureElementClassName,
            gMethods, NELEM(gMethods));
}


} // namespace android
